package com.qumitech.visualnovel.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.qumitech.visualnovel.component.util.DateUtil;
import com.qumitech.visualnovel.model.common.BaseResponse;
import com.qumitech.visualnovel.datasource.console.*;
import com.qumitech.visualnovel.model.dao.console.DeviceLoginStatistics;
import com.qumitech.visualnovel.model.dao.console.DeviceRegisterStatistics;
import com.qumitech.visualnovel.model.dao.console.DeviceRemainStatistics;
import com.qumitech.visualnovel.model.dao.console.DeviceActiveRemainStatistics;
import com.qumitech.visualnovel.model.dao.console.UserDailyStatisticSumDO;
import com.qumitech.visualnovel.pubdef.dto.devicestatistic.DeviceStatisticDTO;
import com.qumitech.visualnovel.service.DeviceStatisticsService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Service
public class DeviceStatisticsServiceImpl implements DeviceStatisticsService {

    @Autowired
    DeviceRegisterStatisticsMapper deviceRegisterStatisticsMapper;

    @Autowired
    DateUtil dateUtil;

    @Autowired
    DeviceLoginStatisticsMapper deviceLoginStatisticsMapper;

    @Autowired
    DeviceRemainStatisticsMapper deviceRemainStatisticsMapper;

    @Autowired
    DeviceActiveRemainStatisticsMapper deviceActiveRemainStatisticsMapper;

    @Autowired
    UserDailyStatisticSumDOMapper userDailyStatisticSumDOMapper;

    private JSONObject getSeriesItem(String matchTypeName, Map<String,Long> tempMap)
    {
        JSONObject seriesItem = new JSONObject();
        seriesItem.put("name", matchTypeName);
        seriesItem.put("type", "line");
        JSONArray seriesItemDataList = new JSONArray();
        for(String key : tempMap.keySet()) {
            seriesItemDataList.add(tempMap.get(key));
        }
        seriesItem.put("data", seriesItemDataList);
        JSONObject areaStyle = JSONObject.parseObject("{normal: {}}");
        seriesItem.put("areaStyle", areaStyle);
        return seriesItem;
    }

    private JSONObject getLine(Map<String,Long> tempMap, String startTime, String endTime, String matchTypeName){
        JSONArray xAxis = new JSONArray();

        JSONObject legend = new JSONObject();
        JSONArray legendList = new JSONArray();
        legendList.add(tempMap);
        legend.put("data",legendList);

        List<String> dateList= dateUtil.getnDayList(startTime, endTime);
        JSONObject xAxisData = new JSONObject();
        xAxisData.put("data", JSONArray.parseArray(JSON.toJSONString(dateList)));
        xAxis.add(xAxisData);

        JSONArray series = new JSONArray();
        series.add(getSeriesItem(matchTypeName, tempMap));

        JSONObject yAxis = new JSONObject();
        yAxis.put("type", "value");

        JSONObject resObj = new JSONObject();
        resObj.put("xAxis", xAxis);
        resObj.put("series", series);
        resObj.put("yAxis", yAxis);
        resObj.put("legend", legend);
        return resObj;
    };

    private JSONObject getLines(String startTime, String endTime, List <DeviceStatisticDTO> deviceRegisterStatisticsList) {
        JSONObject legend = new JSONObject();
        JSONArray legendList = new JSONArray();
        legend.put("data",legendList);

        JSONArray xAxis = new JSONArray();
        List<String> dateList= dateUtil.getnDayList(startTime, endTime);
        JSONObject xAxisData = new JSONObject();
        xAxisData.put("data", JSONArray.parseArray(JSON.toJSONString(dateList)));
        xAxis.add(xAxisData);

        JSONArray series = new JSONArray();
        boolean isFirst = true;
        String lastType = null;
        Map<String,Long>  tempMap = null;
        for (DeviceStatisticDTO deviceRegisterStatistics: deviceRegisterStatisticsList)
        {
            if(isFirst)
            {
                tempMap = dateUtil.GetNDaysMap(startTime,endTime);
                lastType = deviceRegisterStatistics.getType();
                isFirst = false;
            }
            if (!lastType.equals(deviceRegisterStatistics.getType()))
            {

                legendList.add(lastType);
                series.add(getSeriesItem(lastType, tempMap));
                lastType = deviceRegisterStatistics.getType();
                tempMap = dateUtil.GetNDaysMap(startTime,endTime);
            }
            tempMap.put(dateUtil.dateToStr(deviceRegisterStatistics.getTargetDate()), deviceRegisterStatistics.getData());
        }
        if(lastType !=null)
        {
            legendList.add(lastType);
            series.add(getSeriesItem(lastType, tempMap));
        }
        JSONObject resObj = new JSONObject();
        resObj.put("legend", legend);
        resObj.put("xAxis", xAxis);
        resObj.put("series", series);
        return resObj;
    }

    @Override
    public JSONObject getRegisterLine(String type, String channel, String version, String system, String gameType, String appName, String startTime, String endTime) {
        List <DeviceStatisticDTO> deviceRegisterStatisticsList = deviceRegisterStatisticsMapper.getLine(type, channel,version,system,gameType,appName,startTime, endTime);
        return getLines(startTime, endTime, deviceRegisterStatisticsList);
    }

    @Override
    public List<DeviceRegisterStatistics> getRegisterList(String channel, String version, String system, String gameType, String appName, String startTime, String endTime, int offset, int limit, String orderType, String orderBy) {
        List<DeviceRegisterStatistics> deviceRegisterStatisticsList = deviceRegisterStatisticsMapper.getList(channel,version,system,gameType,appName,startTime,endTime,offset,limit,orderType,orderBy);

        for(DeviceRegisterStatistics deviceRegisterStatistics: deviceRegisterStatisticsList)
        {
            if(channel == null) {
                deviceRegisterStatistics.setAppChannel("全部");
            }
            else {
                deviceRegisterStatistics.setAppChannel(channel);
            }
            if(version == null) {
                deviceRegisterStatistics.setAppVersion("全部");
            }
            else {
                deviceRegisterStatistics.setAppVersion(version);
            }
            if(gameType == null) {
                deviceRegisterStatistics.setGameType("全部");
            }
            else {
                deviceRegisterStatistics.setGameType(gameType);
            }
            if (appName == null) {
                deviceRegisterStatistics.setAppName("全部");
            } else {
                deviceRegisterStatistics.setAppName(appName);
            }
        }

        return deviceRegisterStatisticsList;
    }

    @Override
    public int getRegisterCount(String channel, String version, String system, String gameType, String appName, String startTime, String endTime) {
        return deviceRegisterStatisticsMapper.getCount(channel,version,system,gameType,appName,startTime,endTime);
    }

    @Override
    public JSONObject getLoginLine(String type, String channel, String version, String system, String gameType, String appName, String startTime, String endTime) {
        List <DeviceStatisticDTO> statisticDTOS = deviceLoginStatisticsMapper.getLine(type, channel,version,system,gameType,appName,startTime, endTime);
        return getLines(startTime, endTime, statisticDTOS);
    }

    @Override
    public List<DeviceLoginStatistics> getLoginList(String channel, String version, String system, String gameType, String appName, String startTime, String endTime, int offset, int limit, String orderType, String orderBy) {
        List<DeviceLoginStatistics> deviceLoginStatisticsList = deviceLoginStatisticsMapper.getList(channel,version,system,gameType,appName,startTime,endTime,offset,limit,orderType,orderBy);

        for(DeviceLoginStatistics deviceLoginStatistics: deviceLoginStatisticsList)
        {
            if(channel == null) {
                deviceLoginStatistics.setAppChannel("全部");
            }
            else {
                deviceLoginStatistics.setAppChannel(channel);
            }
            if(version == null) {
                deviceLoginStatistics.setAppVersion("全部");
            }
            else {
                deviceLoginStatistics.setAppVersion(version);
            }
            if(gameType == null) {
                deviceLoginStatistics.setGameType("全部");
            }
            else {
                deviceLoginStatistics.setGameType(gameType);
            }
            if (appName == null) {
                deviceLoginStatistics.setAppName("全部");
            } else {
                deviceLoginStatistics.setAppName(appName);
            }
        }
        return deviceLoginStatisticsList;
    }

    @Override
    public int getLoginCount(String channel, String version, String system, String gameType, String appName, String startTime, String endTime) {
        return deviceLoginStatisticsMapper.getCount(channel,version,system,gameType,appName,startTime,endTime);
    }


    @Override
    public JSONObject getRemainLine(String appName, String channel,String appVersion, String system, String startTime, String endTime) {
        List<DeviceRemainStatistics> remainDeviceList = deviceRemainStatisticsMapper.getRemainDeviceList(startTime, endTime, appName, channel, appVersion, system);

        String[] legendStrList = {"次日留存", "3日留存", "7日留存", "14日留存", "30日留存", "次日留存率", "3日留存率", "7日留存率", "14日留存率", "30日留存率"};

        JSONObject legend = new JSONObject();
        JSONArray legendList = new JSONArray();
        legend.put("data", legendList);
        JSONArray xAxis = new JSONArray();
        List<String> dateList = dateUtil.getnDayList(startTime, endTime);
        JSONObject xAxisData = new JSONObject();
        xAxisData.put("data", JSONArray.parseArray(JSON.toJSONString(dateList)));
        xAxis.add(xAxisData);
        JSONArray series = new JSONArray();
        for (int i = 0; i < 10; i++) {
            legendList.add(legendStrList[i]);
            Map<String, Long> tempMap = dateUtil.GetNDaysMap(startTime, endTime);
            for (DeviceRemainStatistics remainUserCount : remainDeviceList) {
                tempMap.put(dateUtil.dateToStr(remainUserCount.getTargetDate()), Long.valueOf(remainUserCount.formatData(i)));
            }
            series.add(getSeriesItem(legendStrList[i], tempMap));
        }
        JSONObject resObj = new JSONObject();
        resObj.put("legend", legend);
        resObj.put("xAxis", xAxis);
        resObj.put("series", series);
        return resObj;
    }

    @Override
    public JSONObject getRemainList(String appName, String channel,String appVersion,String system, String startTime, String endTime, int offset, int limit) {
        JSONArray dataItems = new JSONArray();
        List<DeviceRemainStatistics> remainDeviceList = deviceRemainStatisticsMapper.getRemainDeviceList(startTime, endTime, appName, channel, appVersion, system);
        for (int i = offset; i < offset + limit && i < remainDeviceList.size(); i++) {
            DeviceRemainStatistics temp = remainDeviceList.get(i);
            temp.setAppVersion(appVersion==null ? "-" : appVersion);
            dataItems.add(temp.formatJson());
        }
        return new BaseResponse(dataItems);
    }

    @Override
    public JSONObject getActiveRemainLine(String appName, String channel, String appVersion, String system, String startTime, String endTime) {
        String[] legendStrList = {"次日留存", "3日留存", "7日留存", "14日留存", "30日留存", "次日留存率", "3日留存率", "7日留存率", "14日留存率", "30日留存率"};
        List<DeviceActiveRemainStatistics> activeRemainUserCountList = deviceActiveRemainStatisticsMapper.getActiveRemainDeviceList(startTime, endTime, appName, channel, appVersion, system);

        JSONObject legend = new JSONObject();
        JSONArray legendList = new JSONArray();
        legend.put("data", legendList);
        JSONArray xAxis = new JSONArray();
        List<String> dateList = dateUtil.getnDayList(startTime, endTime);
        JSONObject xAxisData = new JSONObject();
        xAxisData.put("data", JSONArray.parseArray(JSON.toJSONString(dateList)));
        xAxis.add(xAxisData);
        JSONArray series = new JSONArray();
        for (int i = 0; i < 10; i++) {
            legendList.add(legendStrList[i]);
            Map<String, Long> tempMap = dateUtil.GetNDaysMap(startTime, endTime);
            for (DeviceActiveRemainStatistics activeRemainUserCount : activeRemainUserCountList) {
                tempMap.put(dateUtil.dateToStr(activeRemainUserCount.getTargetDate()), Long.valueOf(activeRemainUserCount.formatData(i)));
            }
            series.add(getSeriesItem(legendStrList[i], tempMap));
        }
        JSONObject resObj = new JSONObject();
        resObj.put("legend", legend);
        resObj.put("xAxis", xAxis);
        resObj.put("series", series);
        return resObj;
    }

    @Override
    public JSONObject getActiveRemainList(String appName, String channel, String appVersion, String system, String startTime, String endTime, int offset, int limit ) {
        JSONArray dataItems = new JSONArray();
        List<DeviceActiveRemainStatistics> activeRemainUserCountList = deviceActiveRemainStatisticsMapper.getActiveRemainDeviceList(startTime, endTime, appName, channel, appVersion, system);
        for (int i = offset; i < offset + limit && i < activeRemainUserCountList.size(); i++) {
            DeviceActiveRemainStatistics temp = activeRemainUserCountList.get(i);
            temp.setAppVersion(appVersion==null ? "-" : appVersion);
            dataItems.add(temp.formatJson());
        }
        return new BaseResponse(dataItems);
    }

    @Override
    public JSONObject getUserDailyStatisticSumList(String type, String startTime, String endTime, int offset, int limit) {
        int count = userDailyStatisticSumDOMapper.getCount(startTime, endTime);
        List<JSONObject> result = new ArrayList<JSONObject>();
        List<UserDailyStatisticSumDO> items = userDailyStatisticSumDOMapper.getList(startTime, endTime, offset, limit);
        for (UserDailyStatisticSumDO item : items) {
            result.add(item.getDeviceStatistic(type));
        }
        return new BaseResponse(result, count);
    }
}
